Skip to content

Feat: [BADA-364] 알림 비동기 처리#388

Merged
dionisos198 merged 1 commit intodevelopfrom
feature/BADA-364-async-alarm
Aug 5, 2025
Merged

Feat: [BADA-364] 알림 비동기 처리#388
dionisos198 merged 1 commit intodevelopfrom
feature/BADA-364-async-alarm

Conversation

@dionisos198
Copy link
Copy Markdown
Collaborator

#️⃣연관된 이슈

close: #387

🚀 작업 내용

  • 알림 비동기 처리

🔍 리뷰 요청 사항

알림 비동기 처리

@dionisos198 dionisos198 added this to the 🏷️ 대여 milestone Aug 5, 2025
@dionisos198 dionisos198 self-assigned this Aug 5, 2025
@dionisos198 dionisos198 added the ✨ Feature 기능 개발 label Aug 5, 2025
@github-actions
Copy link
Copy Markdown

github-actions bot commented Aug 5, 2025

Failed to generate code suggestions for PR

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Implements asynchronous notification processing to improve system performance by preventing blocking operations during notification handling.

  • Added Spring async configuration with custom thread pool executor
  • Converted notification services to use asynchronous processing with @async annotation
  • Refactored event listeners to use @eventlistener instead of @TransactionalEventListener for better async handling
  • Extracted restock targeting logic into a separate service class for better separation of concerns

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
SpringAsyncConfig.java Configures async processing with custom thread pool settings
ReportNotificationService.java Adds @async annotation to enable asynchronous report notification processing
ReportListenerEvent.java Changes from @TransactionalEventListener to @eventlistener for async compatibility
RestockDeleteTargetingService.java New service class extracted from event listener to handle restock targeting logic
ReStockRepository.java Adds join fetch optimization for user data retrieval
RentalListenerEvent.java Refactors to use extracted service and adds @async for asynchronous processing

@github-actions
Copy link
Copy Markdown

github-actions bot commented Aug 5, 2025

Overall Project 17.8% -0.72%
Files changed 4.08%

File Coverage
RentalListenerEvent.java 6.56% -18.03%
RestockDeleteTargetingService.java 4.6% -95.4%
ReportNotificationService.java 3.75% 🍏
ReportListenerEvent.java 0% 🍏

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Aug 5, 2025

Walkthrough

이번 변경사항에서는 Restock(재입고) 알림 대상자 선정 및 알림 로직을 별도의 서비스(RestockDeleteTargetingService)로 분리하고, 기존 이벤트 리스너들의 동작 방식을 비동기 실행(@Async)으로 전환하였습니다. Restock 관련 이벤트 리스너는 트랜잭션 기반 실행에서 스레드풀 기반 비동기 실행으로 변경되었으며, Report(신고) 관련 이벤트 리스너도 트랜잭션 커밋 후 실행에서 단순 이벤트 리스너로 변경되었습니다. 또한, 비동기 처리를 위한 스레드풀 설정을 제공하는 Spring 설정 클래스가 추가되었습니다. 일부 JPA 쿼리(fetch join 추가)와 불필요한 의존성 및 메서드 정리가 함께 이루어졌습니다.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15–25 minutes

  • 복수의 클래스 신설 및 이동, 비동기 처리 전환, JPA 쿼리 변경, 이벤트 리스너 어노테이션 변경, 트랜잭션 처리 방식 수정 등 중간 난이도의 구조적 변화가 포함되어 있습니다.
  • 신규 서비스(RestockDeleteTargetingService)의 로직 검토와 기존 로직에서의 위임 및 삭제, 그리고 비동기 실행 환경 설정 확인이 필요합니다.
  • 전체적으로 20분 내외의 리뷰 시간이 예상됩니다.

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/BADA-364-async-alarm

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0e66000 and 9d2cdbe.

📒 Files selected for processing (6)
  • src/main/java/com/TwoSeaU/BaData/domain/rental/event/RentalListenerEvent.java (2 hunks)
  • src/main/java/com/TwoSeaU/BaData/domain/rental/repository/ReStockRepository.java (1 hunks)
  • src/main/java/com/TwoSeaU/BaData/domain/rental/service/RestockDeleteTargetingService.java (1 hunks)
  • src/main/java/com/TwoSeaU/BaData/domain/trade/event/ReportListenerEvent.java (2 hunks)
  • src/main/java/com/TwoSeaU/BaData/domain/trade/service/ReportNotificationService.java (2 hunks)
  • src/main/java/com/TwoSeaU/BaData/global/config/SpringAsyncConfig.java (1 hunks)
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: dionisos198
PR: Ureca-Final-Project-Team2/be_badata#366
File: src/main/java/com/TwoSeaU/BaData/domain/rental/event/RestockEvent.java:17-23
Timestamp: 2025-08-03T14:38:14.569Z
Learning: RestockEvent.from() 팩토리 메서드에서 null 검증은 불필요하다. 파라미터가 null일 경우 이전 서비스 코드에서 이미 오류가 발생하므로 중복 검증을 피한다.
Learnt from: dionisos198
PR: Ureca-Final-Project-Team2/be_badata#366
File: src/main/java/com/TwoSeaU/BaData/domain/rental/event/RentalListenerEvent.java:89-90
Timestamp: 2025-08-03T14:37:51.472Z
Learning: 재입고 알림 시스템에서는 예약이 취소된 기간(rentalStart, rentalEnd)을 기준으로 가용 수량을 확인한다. 이는 취소된 예약 기간을 통해 재입고 알림이 트리거되는 이벤트 기반 비즈니스 로직에 부합한다.
Learnt from: dionisos198
PR: Ureca-Final-Project-Team2/be_badata#102
File: src/main/java/com/TwoSeaU/BaData/domain/rental/service/RestockService.java:48-48
Timestamp: 2025-07-14T07:27:02.452Z
Learning: 재입고 알림(ReStock) 비즈니스 로직: 재입고 알림은 해당 기간에 예약이 불가능할 때만 신청할 수 있다. 예약 가능한 수량이 충분하다면 재입고 알림을 신청할 수 없고 예외가 발생한다.
📚 Learning: review-reservation 간 1:1 관계에서 외래키 제약조건은 데이터 무결성을 보장하지만, jpa 지연 로딩으로 인한 lazyinitializationexception 방...
Learnt from: dionisos198
PR: Ureca-Final-Project-Team2/be_badata#144
File: src/main/java/com/TwoSeaU/BaData/domain/rental/dto/response/ShowReviewResponse.java:34-34
Timestamp: 2025-07-18T05:16:04.655Z
Learning: Review-Reservation 간 1:1 관계에서 외래키 제약조건은 데이터 무결성을 보장하지만, JPA 지연 로딩으로 인한 LazyInitializationException 방지를 위해서는 연관된 User 엔티티도 함께 fetch해야 한다. NPE 체크보다는 쿼리 개선이 더 나은 해결책이다.

Applied to files:

  • src/main/java/com/TwoSeaU/BaData/domain/rental/repository/ReStockRepository.java
📚 Learning: in the be_badata codebase, event classes (like reportemailevent, reportfcmevent) and response dtos c...
Learnt from: dionisos198
PR: Ureca-Final-Project-Team2/be_badata#357
File: src/main/java/com/TwoSeaU/BaData/domain/trade/event/ReportFcmEvent.java:12-14
Timestamp: 2025-08-02T19:06:31.945Z
Learning: In the be_badata codebase, Event classes (like ReportEmailEvent, ReportFcmEvent) and Response DTOs consistently use non-final private fields (e.g., `private String contents`, `private List<String> tokens`). Request DTOs have mixed patterns with some using final fields. The field name "contents" is consistently used across report-related events rather than "content".

Applied to files:

  • src/main/java/com/TwoSeaU/BaData/domain/trade/event/ReportListenerEvent.java
  • src/main/java/com/TwoSeaU/BaData/domain/rental/event/RentalListenerEvent.java
📚 Learning: 재입고 알림 시스템에서는 예약이 취소된 기간(rentalstart, rentalend)을 기준으로 가용 수량을 확인한다. 이는 취소된 예약 기간을 통해 재입고 알림이 트리거되는 이...
Learnt from: dionisos198
PR: Ureca-Final-Project-Team2/be_badata#366
File: src/main/java/com/TwoSeaU/BaData/domain/rental/event/RentalListenerEvent.java:89-90
Timestamp: 2025-08-03T14:37:51.472Z
Learning: 재입고 알림 시스템에서는 예약이 취소된 기간(rentalStart, rentalEnd)을 기준으로 가용 수량을 확인한다. 이는 취소된 예약 기간을 통해 재입고 알림이 트리거되는 이벤트 기반 비즈니스 로직에 부합한다.

Applied to files:

  • src/main/java/com/TwoSeaU/BaData/domain/rental/event/RentalListenerEvent.java
📚 Learning: restockevent.from() 팩토리 메서드에서 null 검증은 불필요하다. 파라미터가 null일 경우 이전 서비스 코드에서 이미 오류가 발생하므로 중복 검증을 피한다....
Learnt from: dionisos198
PR: Ureca-Final-Project-Team2/be_badata#366
File: src/main/java/com/TwoSeaU/BaData/domain/rental/event/RestockEvent.java:17-23
Timestamp: 2025-08-03T14:38:14.569Z
Learning: RestockEvent.from() 팩토리 메서드에서 null 검증은 불필요하다. 파라미터가 null일 경우 이전 서비스 코드에서 이미 오류가 발생하므로 중복 검증을 피한다.

Applied to files:

  • src/main/java/com/TwoSeaU/BaData/domain/rental/event/RentalListenerEvent.java
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-test
🔇 Additional comments (5)
src/main/java/com/TwoSeaU/BaData/domain/trade/service/ReportNotificationService.java (1)

34-36: @async@transactional 조합 검토 필요

sendReportNotification 메서드에
@Transactional(readOnly = true)@Async("threadPoolTaskExecutor")를 함께 적용하면
비동기 스레드에서 트랜잭션 컨텍스트가 정상적으로 전파되지 않을 수 있습니다.
또한 이 메서드는 주로 이벤트 발행 위주이므로 읽기 전용 트랜잭션이 꼭 필요한지 재검토가 필요합니다.

  • 파일: src/main/java/com/TwoSeaU/BaData/domain/trade/service/ReportNotificationService.java
  • 대상 메서드: public void sendReportNotification(final Report report)

전체 코드베이스에서 동일한 패턴이 다른 곳에 없는지, 혹은 이 조합이 의도한 대로 동작하는지 확인 부탁드립니다.

src/main/java/com/TwoSeaU/BaData/domain/rental/repository/ReStockRepository.java (1)

13-19: 성능 최적화가 잘 적용되었습니다.

join fetch r.user u 추가로 N+1 쿼리 문제를 방지하고 LazyInitializationException을 예방했습니다. 새로운 RestockDeleteTargetingService에서 사용자 데이터에 접근할 때 효율적인 쿼리가 가능합니다.

src/main/java/com/TwoSeaU/BaData/domain/rental/event/RentalListenerEvent.java (2)

35-35: 서비스 분리가 잘 이루어졌습니다.

RestockDeleteTargetingService로 책임을 분리하여 코드의 응집도와 재사용성이 향상되었습니다. 복잡한 타겟팅 로직이 별도 서비스로 캡슐화되어 테스트와 유지보수가 용이해졌습니다.


37-38: 알림 발송 순서 변경 검토 필요
sendFcmToken 호출이 sendEmail 호출보다 먼저 실행되도록 변경된 것으로 보입니다. 사용자 경험 관점에서 의도된 변경인지 확인해주세요.

  • 파일: src/main/java/com/TwoSeaU/BaData/domain/rental/event/RentalListenerEvent.java
  • 라인: 37–38

rg 검색 결과, 코드베이스 내에서 이전 발송 순서를 참조할 수 있는 다른 구현 예제가 발견되지 않았습니다. 변경 사항이 의도된 것인지 다시 한번 검토 부탁드립니다.

src/main/java/com/TwoSeaU/BaData/domain/rental/service/RestockDeleteTargetingService.java (1)

29-30: 트랜잭션 전파 설정 정상 확인됨

RentalListenerEvent에서

@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void handleRestockDeleteEvent(RestockDeleteEvent restockEvent) {
    List<User> sendTargetUser = restockDeleteTargetingService.getSendTargetUser(...);
    …
}

와 같이 부모 트랜잭션(예약 취소)이 커밋된 후에 getSendTargetUser가 호출되므로, REQUIRES_NEW 프로퍼게이션이 커밋된 변경사항을 정상적으로 조회할 수 있습니다.

  • 검증 위치:
    src/main/java/com/TwoSeaU/BaData/domain/rental/event/RentalListenerEvent.java – handleRestockDeleteEvent

따라서 추가 수정이나 검증은 필요 없으며, 해당 리뷰 코멘트는 무시해주세요.

Likely an incorrect or invalid review comment.

@dionisos198 dionisos198 merged commit 0c44d11 into develop Aug 5, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ Feature 기능 개발

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BADA-364] [FEAT] 알림 비동기 처리

3 participants